﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects.DataClasses;
using System.Data.Objects;
using System.Transactions;
using System.Reflection;

namespace Sys.WebRes.Data
{
    public partial class ResourceSysEntities
    {
        /// <summary>
        /// 初始化Master数据，并载入到枚举类型中
        /// </summary>
        public void InitializeMaster()
        {
            using (var tran = DB.NewTran)
            {
                SysConfig.Initialize(this);

                Language.Initialize(this);
                ResStatusType.Initialize(this);
                ResType.Initialize(this);
                AttachUrlType.Initialize(this);
                ResAttachLinkType.Initialize(this);

                int count = this.SaveChanges();
                tran.Complete();
                if (count > 0)
                {
                    System.Diagnostics.Debug.WriteLine("数据库初始化成功，Master数据被成功载入！");
                }
            }
        }

        private DateTime Now_ = DateTime.MinValue;

        public DateTime Now
        { 
            get 
            {
                if (this.Now_ == DateTime.MinValue)
                {
                    this.Now_ = DateTime.Now;
                }

                return this.Now_;
            } 
        }
    }

    public class DB
    {
        public static ResourceSysEntities New
        {
            get { return new ResourceSysEntities(); }
        }

        public static TransactionScope NewTran
        {
            get { return new TransactionScope(); }
        }
    }


    public static class ExternClass
    {
        public static void DeleteAllData<T>(this ObjectQuery<T> query)
        {
            query.ToList().ForEach(p => query.Context.DeleteObject(p));

        }

        public static T CopyTo<T>(this EntityObject entity, T to)
        {
            var fType = entity.GetType();
            var tType = to.GetType();
            foreach (var tp in tType.GetProperties())
            {
                var fp = fType.GetProperty(tp.Name);
                if (fp != null && tp.PropertyType == fp.PropertyType
                    && tp.PropertyType.IsSimpleType())
                {
                    var value = fp.GetValue(entity, null);
                    tp.SetValue(to, value, null);
                }
            }

            return to;
        }

        public static T CopyFrom<T>(this EntityObject entity, T from)
        {
            var fType = from.GetType();
            var tType = entity.GetType();
            foreach (var fp in fType.GetProperties())
            {
                var tp = tType.GetProperty(fp.Name);
                if (tp != null && fp.PropertyType == tp.PropertyType
                    && tp.Name != "ID" && fp.PropertyType.IsSimpleType())
                {
                    var value = fp.GetValue(from, null);
                    tp.SetValue(entity, value, null);
                }
            }

            return from;
        } 

        public static T Clone<T>(this object from, T to)
        {
            var fType = from.GetType();
            var tType = to.GetType();
            foreach (var p in tType.GetProperties())
            {
                var sp = fType.GetProperty(p.Name);
                if (sp != null && p.PropertyType == sp.PropertyType && p.PropertyType.IsSimpleType())
                {
                    var value = sp.GetValue(from, null);
                    p.SetValue(to, value, null);
                }
            }

            return to;
        }

        private static bool IsSimpleType(this Type type)
        {
            Type[] types = new Type[] { 
                typeof(string),
                typeof(int),
                typeof(int?),
                typeof(long),
                typeof(long?),
                typeof(DateTime),
                typeof(DateTime?),
            };

            return (types.FirstOrDefault(t=>t == type) != null);
        }
    }

    public class RecordNotFoundException : Exception
    {
        public int ID { get; set; }
        public Type Type { get; set; }
        public RecordNotFoundException(int id, Type type, string message = null)
            :base(message)
        {
            this.ID = id;
            this.Type = type;
        }
    }
}